<?php

namespace app\index\controller;

use app\common\controller\Apicommon;
use app\index\model\Device;
use app\index\model\DeviceCategory;
use app\index\model\Door;
use app\index\model\GearRecord;
use app\index\model\MemberRecord;
use app\index\model\User;
use hongmo\Hongmo;
use think\App;

/**
 * 扫描虹膜操作
 * @package app\index\controller
 */
class Work extends Apicommon
{
    private $dooroperate = null;

    public function initialize()
    {
        //parent::initialize();
        header('Access-Control-Allow-Headers: content-type,authorization,token');
        header('Access-Control-Allow-Methods: PUT, GET, POST, DELETE, OPTIONS');
        header('Access-Control-Allow-Origin: *');
        if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
            echo 1;
            die;
        }
    }

    public function __construct(App $app = null)
    {
        parent::__construct($app);

        $this->dooroperate = new Dooroperate();
    }

    /**
     * 首页
     */
    public function index()
    {
        // 显示全屏按钮
        $btn_full_screen = input('btn_fullsc', false);
        $this->assign('full_screen_btn', $btn_full_screen);
        return view();
    }

    /**
     * 扫描虹膜开柜门
     */
    public function openDoorByiris()
    {
        $opt = $this->request->request('opt');
        if (!in_array($opt, ['get', 'back'])) {
            $this->error_json('操作有误', [
                'username' => '',
                'user_serial' => ''
            ]);
        }

        // 虹膜扫描识别用户ID
        $hongmo = new Hongmo();
        $user_id = $hongmo->shibiede();
        if (!$user_id) {
            $this->error_json($hongmo->getError(), [
                'username' => '',
                'user_serial' => ''
            ]);
        }

        $user = User::get($user_id);
        if (!$user) $this->error_json('用户信息有误', [
            'username' => '',
            'user_serial' => ''
        ]);

        // 查询用户可以使用的设备类别
        $device_cate = $user->device_cate;
        if (empty($device_cate)) {
            if (!$user) $this->error_json('用户可操作设备有误', [
                'username' => '',
                'user_serial' => ''
            ]);
        }
        $arr_device_cate = explode(',', trim($device_cate, ','));
        $device_list = DeviceCategory::whereIn('id', $arr_device_cate)->field('id,name')->select();
        // 可操作设备类别为多个，则需要手动选择
        if ($device_list && count($device_list) > 1) {
            $this->success_json('请选择设备', [
                'userid' => $user->id,
                'username' => $user->username,
                'user_serial' => $user->user_serial,
                'device' => $device_list
            ]);
        }

        // 用户使用中的设备列表为空，则为取设备
        if ($opt == 'get' && empty($user->device_list)) {
            return $this->getDevice($user, trim($device_cate, ','));
        } else {
            if ($opt == 'get') {
                $this->error_json('您有设备未归还，请先归还设备', [
                    'username' => $user->username,
                    'user_serial' => $user->user_serial
                ]);
            }
            if (empty($user->device_list)) {
                $this->error_json('您没有需要归还的设备', [
                    'username' => $user->username,
                    'user_serial' => $user->user_serial
                ]);
            }
            // 否侧为返还设备
            return $this->backDevice($user, trim($device_cate, ','));
        }
    }

    /**
     * 手动选择设备
     */
    public function open_door_by_choice()
    {
        $opt = $this->request->request('opt');
        if (!in_array($opt, ['get', 'back'])) {
            $this->error_json('操作有误', [
                'username' => '',
                'user_serial' => ''
            ]);
        }

        $user_id = input('userid');
        $open_device_cate = input('device_cate');
        if (!$user_id || !$open_device_cate) {
            $this->error_json('操作有误', [
                'username' => '',
                'user_serial' => ''
            ]);
        }

        $user = User::get($user_id);
        if (!$user) $this->error_json('用户信息有误', [
            'username' => '',
            'user_serial' => ''
        ]);

        // 查询用户可以使用的设备类别
        $device_cate = $user->device_cate;
        if (empty($device_cate)) {
            if (!$user) $this->error_json('用户可操作设备有误', [
                'username' => '',
                'user_serial' => ''
            ]);
        }
        $arr_device_cate = explode(',', $device_cate);
        if (!in_array($open_device_cate, $arr_device_cate)) {
            $this->error_json('用户可操作设备有误', [
                'username' => '',
                'user_serial' => ''
            ]);
        }

        // 用户使用中的设备列表为空，则为取设备
        if ($opt == 'get') {
            return $this->getDevice($user, $open_device_cate);
        } else {
            if (empty($user->device_list)) {
                $this->error_json('您没有需要归还的设备', [
                    'username' => $user->username,
                    'user_serial' => $user->user_serial
                ]);
            }
            // 否侧为返还设备
            return $this->backDevice($user, $open_device_cate);
        }
    }

    /**
     * 取设备
     * @param User $user 用户ID
     * @param int $device_cate 设备分类
     */
    private function getDevice($user, $device_cate)
    {
        // 查询前五个低容量的柜子
        $field = "
            door.id door_id,
            count(door.id) num,
            door.get_from_here
        ";

        $where = [
            ['door.is_security', '=', 0],   // 排除安检柜
            ['door.status', 'neq', 0],        // 柜门状态不为空
            ['door.last_battery_full', '<', time()],  // 柜柜子中设备最后充电期限
            ['device_category', '=', $device_cate]
        ];

        $list = Door::alias('door')->field($field)
            ->leftJoin('device dev', 'dev.door_id = door.id')
            ->where($where)
            ->group('door.id')
            ->limit(Door::$low_num_door)
            ->order('num', 'asc') // 按设备数量增序
            ->select()->toArray();

        if (empty($list)) {
            $this->error_json('没有可操作的柜子', [
                'username' => '',
                'user_serial' => ''
            ]);
        }

        // 检查有没有推荐打开的柜子
        $advice_by_id = array_column($list, 'get_from_here', 'door_id');

        // 以柜门ID为键，记录柜门是否推荐打开
        $advice = array_search(1, $advice_by_id);

        // 有推荐的柜子则取第一个推荐的柜子,没有推荐则取第一个柜子
        $the_door_id = (false !== $advice) ? $advice : array_keys($advice_by_id)[0];
        $gear_id = Door::where($the_door_id)->value('gear_id');

        // 找出下一个推荐使用的柜子
        $door_ids = array_column($list, 'door_id');
        $current_index = array_search($the_door_id, $door_ids);
        $next_door = isset($door_ids[$current_index + 1]) ? $door_ids[$current_index + 1] : $door_ids[0];

        // 将其他柜子设为不推荐
        Door::update(['get_from_here' => 0], [['id', 'in', implode(',', $door_ids)]]);
        // 下一个柜子设为推荐
        Door::update(['get_from_here' => 1], [['id', '=', $next_door]]);

        // 开柜门
        $res = $this->dooroperate->openDoor($the_door_id, $user->id, 1);
        if ($res) {
            $this->success_json('请尽快到' . $gear_id . '号柜' . $the_door_id . '号门取用，取用后请随手关门', [
                'username' => $user->username,
                'user_serial' => $user->user_serial
            ]);
        } else {
            $this->error_json($this->dooroperate->getError(), [
                'username' => '',
                'user_serial' => ''
            ]);
        }
    }

    /**
     * 返还设备
     * @param User $user 用户模型
     * @param int $device_cate 设备分类
     */
    private function backDevice($user, $device_cate)
    {
        // 查询用户使用中的设备
        $wait_back_list = Device::whereIn('id', $user->device_list)->column('category_id,device_model,device_name,warning_time');
        $wait_back = null;
        foreach ($wait_back_list as $wb_i) {
            if ($wb_i['category_id'] == $device_cate) {
                $wait_back = $wb_i;
            }
        }
        if (empty($wait_back)) {
            $this->error_json('您没有使用该类型设备', [
                'username' => $user->username,
                'user_serial' => $user->user_serial
            ]);
        }

        // 设备已到安检时间，则返还到安检柜
        if ($wait_back['warning_time'] <= date('Y-m-d')) {
            return $this->backToCheckBox($user,$wait_back);
        } else {
            return $this->backDeviceNormal($user, $wait_back);
        }
    }

    /**
     * 正常返还设备
     * @param User $user
     * @param Device $device 设备模型
     */
    private function backDeviceNormal($user, $device)
    {
        // 查询前五个高容量的柜子
        $field = "
            door.id door_id,
            count(door.id) num,
            door.back_to_here
        ";

        $list = Door::alias('door')->field($field)
            ->leftJoin('device dev', 'dev.door_id = door.id')
            ->where([
                ['door.is_security', '=', 0],   // 排除安检柜
                ['door.status', 'neq', 2],        // 柜门状态正常  状态:1正常,0空,2满
//                ['door.last_battery_full', '>', time()], // 柜中设备电池未充满
            ])
            ->where([
                'door.device_category' => $device['category_id'],
                'door.device_name' => $device['device_name'],
                'door.device_model' => $device['device_model'],
            ])
            ->group('door.id')
            ->limit(Door::$low_num_door)
            ->order('num', 'asc')
            ->having('num <= ' . Door::$max_device)
            ->select()->toArray();

        if (empty($list)) {
            $this->error_json('没有可以归还的柜子', [
                'username' => $user->username,
                'user_serial' => $user->user_serial
            ]);
        }

        // 检查有没有推荐打开的柜子
        $canback_by_id = array_column($list, 'back_to_here', 'door_id');

        // 以柜门ID为键，记录柜门是否推荐打开
        $advice = array_search(1, $canback_by_id);

        // 有可以存的柜子则用第一个可以存的柜子,没有指定柜子则用第一个柜子
        $the_door_id = (false !== $advice) ? $advice : array_keys($canback_by_id)[0];
        $gear_id = Door::where($the_door_id)->value('gear_id');

        // 找出下一个推荐使用的柜子
        $door_ids = array_column($list, 'door_id');
        $current_index = array_search($the_door_id, $door_ids);
        $next_door = isset($door_ids[$current_index + 1]) ? $door_ids[$current_index + 1] : $door_ids[0];

        // 将其他柜子设为不推荐
        Door::update(['back_to_here' => 0], [['id', 'in', implode(',', $door_ids)]]);
        // 下一个柜子设为推荐
        Door::update(['back_to_here' => 1], [['id', '=', $next_door]]);

        // 开柜门
        $res = $this->dooroperate->openDoor($the_door_id, $user->id, 1);
        if ($res) {
            // 否则正常返回到柜子中
            $this->success_json('请将您的设备归还到' . $gear_id . '号柜' . $the_door_id . '号门中', [
                'username' => $user->username,
                'user_serial' => $user->user_serial
            ]);
        } else {
            $this->error_json($this->dooroperate->getError(), [
                'username' => '',
                'user_serial' => ''
            ]);
        }
    }

    /**
     * 返还到安检箱子中
     * @param User $user 用户模型
     */
    private function backToCheckBox($user,$goto_other_fun = null)
    {
        // 查找安检柜子
        $door = Door::where([
            ['status', 'neq', 2],
            ['is_security', '=', 1],
        ])->find();

        if (empty($door)) {
            return $this->backDeviceNormal($user, $goto_other_fun);
            // $this->error_json('未找到安检柜', [
            //       'username' => '',
            //       'user_serial' => ''
            //   ]);
        }

        $gear_id = Door::where($door->id)->value('gear_id');

        // 开柜门
        $res = $this->dooroperate->openDoor($door->id, $user->id, 2);
        if ($res) {
            $this->success_json('请将您的设备归还到' . $gear_id . '号柜' . $door->id . '号门中', [
                'username' => $user->username,
                'user_serial' => $user->user_serial
            ]);
        } else {
            $this->error_json($this->dooroperate->getError(), [
                'username' => '',
                'user_serial' => ''
            ]);
        }
    }
}
